#include "oled.h"

static void I2C_Configuration(void);
static void delay(int x);

/**
 * @brief 简单的延时函数
 * @param x 延时时间（相对值）
 */
static void delay(int x)
{
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < 1000; j++)
            __NOP();
    }
}

/**
 * @brief I2C接口初始化配置
 */
static void I2C_Configuration(void)
{
    I2C_InitTypeDef I2C_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能I2C和GPIO时钟
    RCC_APB1PeriphClockCmd(OLED_I2C_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(OLED_I2C_GPIO_CLK, ENABLE);

    // 配置I2C引脚为复用开漏输出
    GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN | OLED_I2C_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(OLED_I2C_GPIO, &GPIO_InitStructure);

    // 配置I2C参数
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 400000;
    
    I2C_Init(OLED_I2C, &I2C_InitStructure);
    I2C_Cmd(OLED_I2C, ENABLE);
}

void OLED_WriteCmd(uint8_t cmd)
{
    while(I2C_GetFlagStatus(OLED_I2C, I2C_FLAG_BUSY));
    
    I2C_GenerateSTART(OLED_I2C, ENABLE);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_MODE_SELECT));
    
    I2C_Send7bitAddress(OLED_I2C, OLED_ADDRESS, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    
    I2C_SendData(OLED_I2C, 0x00);    // 0x00表示写命令
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_SendData(OLED_I2C, cmd);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_GenerateSTOP(OLED_I2C, ENABLE);
}

void OLED_WriteData(uint8_t data)
{
    while(I2C_GetFlagStatus(OLED_I2C, I2C_FLAG_BUSY));
    
    I2C_GenerateSTART(OLED_I2C, ENABLE);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_MODE_SELECT));
    
    I2C_Send7bitAddress(OLED_I2C, OLED_ADDRESS, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    
    I2C_SendData(OLED_I2C, 0x40);    // 0x40表示写数据
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_SendData(OLED_I2C, data);
    while(!I2C_CheckEvent(OLED_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    I2C_GenerateSTOP(OLED_I2C, ENABLE);
}

void OLED_SetPosition(uint8_t page, uint8_t col)
{
    OLED_WriteCmd(0xB0 | page);
    OLED_WriteCmd(0x10 | ((col & 0xF0) >> 4));
    OLED_WriteCmd(0x00 | (col & 0x0F));
}

void OLED_Clear(void)
{
    for(uint8_t page = 0; page < OLED_PAGES; page++) {
        OLED_SetPosition(page, 0);
        for(uint8_t col = 0; col < OLED_WIDTH; col++) {
            OLED_WriteData(0x00);
        }
    }
}

void OLED_Fill(void)
{
    for(uint8_t page = 0; page < OLED_PAGES; page++) {
        OLED_SetPosition(page, 0);
        for(uint8_t col = 0; col < OLED_WIDTH; col++) {
            OLED_WriteData(0xFF);
        }
    }
}

void OLED_Init(void)
{
    I2C_Configuration();
    delay(100);
    
    OLED_WriteCmd(0xAE);
    OLED_WriteCmd(0x20);
    OLED_WriteCmd(0x02);
    OLED_WriteCmd(0x40);
    OLED_WriteCmd(0xA1);
    OLED_WriteCmd(0xC8);
    OLED_WriteCmd(0xA8);
    OLED_WriteCmd(0x3F);
    OLED_WriteCmd(0xD3);
    OLED_WriteCmd(0x00);
    OLED_WriteCmd(0x81);
    OLED_WriteCmd(0xFF);
    OLED_WriteCmd(0xA4);
    OLED_WriteCmd(0xD5);
    OLED_WriteCmd(0x80);
    OLED_WriteCmd(0x8D);
    OLED_WriteCmd(0x14);
    OLED_WriteCmd(0xAF);
} 